<?php

namespace app\api\controller;

use app\api\model\Coupons;
use app\api\model\Designs;
use app\api\model\DesignServices;
use app\api\model\OrderComment;
use app\api\model\Orders;
use app\api\model\Qrcode;
use app\api\model\Refunds;
use app\api\model\UserBalanceLog;
use app\api\model\UserCoupons;
use app\api\model\Users;
use app\api\model\UserVip;
use app\api\model\Wechat;
use app\api\validate\OrderSubscribeValidate;
use app\common\controller\Api;
use Symfony\Component\HttpFoundation\Request;
use think\Cache;
use think\Db;
use think\Log;
use think\Queue;
use Yansongda\Pay\Exceptions\GatewayException;
use Yansongda\Pay\Pay;

/**
 * 订单
 */
class Order extends Api
{
    protected $noNeedLogin = ['comment'];
    protected $noNeedRight = ['*'];


    /**
     * 预约选择页面
     */
    public function subscribe()
    {
        $data = $this->request->post();
        $validate = new OrderSubscribeValidate();
        if (!$validate->batch()->check($data)) {
            $this->error($validate->getError());
        }
        if ($data['orderdata'] == 1 && (!isset($data['time']) || empty($data['time']))) {
            $this->error('预约时间不能为空');
        }
        $order_no = date('YmdHis') . mt_rand(1000, 9999);
        $user_id = $this->auth->getUserId();
        $data['order_no'] = $order_no;
        $data['user_id'] = $user_id;
        //缓存订单信息
        $result = Cache::set($order_no, json_encode($data), 3600);
        $result ? $this->success('请求成功', ['order_no' => $order_no]) : $this->error('请求失败');
    }

    /**
     * 确认预约页面
     */
    public function confirmSubscribe()
    {
        $order_no = $this->request->post('order_no');
        $user_coupon_id = $this->request->post('user_coupon_id');
        if (empty($order_no)) {
            $this->error('订单号不能为空');
        }
        $order = json_decode(Cache::get($order_no), true);
        if (!$order) {
            $this->error('数据已过期，请重新预约');
        }
        //设计师
        $design = Designs::getById($order['design_id']);
        if (!$design) {
            $this->error('预约的设计师不存在');
        }
        if (!$design->isbuy) {
            $this->error('设计师已暂停预约服务');
        }
        $order['design'] = $design;
        $user = Users::find($order['user_id']);
        if (!$user) {
            $this->error('用户不存在');
        }
        //服务项目
        $service = DesignServices::getServices((int)$order['design_service_id']);
        if (!$service) {
            $this->error('选择服务的项目不存在');
        }
        $service_amount = $service->price;
        $service_name = $service->service->service_name;

        //优惠券
        $discount_amount = 0;
        if ($user_coupon_id) {
            $user_coupon = UserCoupons::find($user_coupon_id);
            if (!$user_coupon) {
                $this->error('无效的优惠券');
            }
            if ($user_coupon->status != 1) {
                $this->error('优惠券已过期或已被使用');
            }
            //直接优惠金额
            if ($user_coupon->type == 1) {
                $discount_amount = $user_coupon->discount_amount;
            }
            //折扣
            if ($user_coupon->type == 2) {
                $discount_amount = $user_coupon->discount_amount > 0 ? $service_amount * (10 - $user_coupon->discount_amount) / 10 : 0;
            }
        }
        //会员优惠
        $vip_amount = 0;
        $vip = UserVip::where('name', $user->vip)->find();
        if ($vip && $vip->discount > 0) {
            $vip_amount = ($service_amount - $discount_amount) * (100 - $vip->discount) / 100;
        }
        //可用数量
        $coupon_count = UserCoupons::getCouponCount($order['user_id'], strtotime($order['time']), $order['design_service_id']);
        $order['coupon_count'] = $coupon_count;
        //用户优惠券id
        $order['user_coupon_id'] = $user_coupon_id ?: 0;
        //优惠券优惠金额
        $order['discount_amount'] = numberFormat($discount_amount, 2);
        //服务项目名称
        $order['service_name'] = $service_name;
        //服务价格
        $order['service_amount'] = numberFormat($service_amount, 2);
        //会员优惠金额
        $order['vip_amount'] = numberFormat($vip_amount, 2);
        //订单总价
        $total_amount = $service_amount - $vip_amount - $discount_amount;
        if ($total_amount <= 0) {
            $this->error('支付金额必须大于0元');
        }
        $order['total_amount'] = numberFormat($total_amount, 2);
        $order['service_amount'] = $service_amount;
        $order['total_money'] = $total_amount;
        //刷新订单缓存数据
        Cache::set($order_no, json_encode($order, JSON_UNESCAPED_UNICODE), 7200);
        $this->success('请求成功', ['order' => $order]);
    }

    /**
     * 用户优惠券
     */
    public function userCoupon()
    {
        $time = $this->request->get('time');
        $design_service_id = $this->request->get('design_service_id');
        $length = $this->request->get('length');
        $user_coupon = UserCoupons::getUserCoupons($this->auth->getUserId(), strtotime($time), $design_service_id, $length);
        $user_coupon->items() ? $this->success('请求成功', ['user_coupon' => $user_coupon->items()]) : $this->error('没有数据', [], 2);
    }

    /**
     * 确认支付
     */
    public function payment(Wechat $wechat)
    {
        $order_no = $this->request->post('order_no');
        $type = $this->request->post('type');
        if (empty($order_no) || empty($type)) {
            $this->error('订单号和支付类型都不能为空');
        }
        $data = json_decode(Cache::get($order_no), true);
        if (!$data) {
            $this->error('订单数据已过期，请重新下单');
        }
        $user = Users::find($this->auth->getUserId());
        if (!$user) {
            $this->error('用户不存在');
        }
        //设计师
        $design = Designs::getById($data['design_id']);
        if (!$design) {
            $this->error('预约的设计师不存在');
        }
        if (!$design->isbuy) {
            $this->error('设计师已暂停预约服务');
        }
        //服务总价
        $total_amount = DesignServices::where('id', $data['design_service_id'])->value('price');
        if (numberFormat($total_amount, 2) !== numberFormat($data['service_amount'], 2)) {
            $this->error('支付金额异常');
        }

        //创建订单
        $order = Orders::createOrder($data);
        if (!$order) {
            $this->error('订单生成失败，请联系管理员');
        }

        switch ($type) {
            //账号余额支付
            case 'account':
                if ($user->money <= 0 || $user->money < $order->total_amount) {
                    $this->error('账号余额不足，请先充值');
                }
                Db::startTrans();
                try {
                    //更新用户余额
                    $user->money -= $order->total_amount;
                    $user->save();
                    //更新订单
                    $order->status = 1;
                    $order->type = 'account';
                    $order->save();
                    //更新优惠券已使用
                    if ($order->user_coupon_id) {
                        UserCoupons::where('id', $order->user_coupon_id)->update(['status' => 2]);
                    }
                    //记录余额变化
                    UserBalanceLog::add($user->id, -$order->total_amount, $order->order_no, 2);

                    Db::commit();
                } catch (\Exception $e) {
                    Db::rollback();
                }
                $res = ['order_id' => $order->id];
                break;
            //微信支付
            case 'wechat':
                try {
                    $res = $wechat->miniapp($order, $user->openid, config('wechat.notify_url'));
                } catch (\Exception $e) {
                    throw new GatewayException($e->getMessage(), $e->getCode());
                }
                $res['order_no'] = $order_no;
                break;
        }

        isset($e) ? $this->error('支付失败，请联系管理员') : $this->success('请求成功', $res);
    }

    /**
     * 支付回调
     */
    public function notify(Wechat $wechat)
    {
        $order_no = $this->request->post('order_no');
        if (empty($order_no)) {
            $this->error('订单号不能为空');
        }
        $order = Orders::getOrderByOrderNo($order_no);
        if (!$order) {
            $this->error('订单不存在');
        }
        if ($order->status > 0) {
            $this->success('支付成功', ['order_id' => $order->id]);
        }
        //查询支付结果
        $res = $wechat->find($order_no);
        if ($res['return_code'] === 'SUCCESS' && $res['result_code'] === 'SUCCESS') {
            if ($res['trade_state'] === 'SUCCESS') {
                Db::startTrans();
                try {
                    //更新订单
                    $order->status = 1;
                    $order->type = 'wechat';
                    $order->save();
                    //更新优惠券已使用
                    if ($order->user_coupon_id) {
                        UserCoupons::where('id', $order->user_coupon_id)->update(['status' => 2]);
                    }
                    Db::commit();
                } catch (\Exception $e) {
                    Db::rollback();
                }
                if (isset($e)) {
                    $this->error('支付失败');
                }
                $this->success('支付成功', ['order_id' => $order->id]);
            } else {
                $this->error($res['trade_state_desc'], [], $res['trade_state']);
            }
        } else {
            $this->error('支付失败，请联系管理员');
        }

    }

    /**
     * 支付结果通知
     */
    public function paymentResult(Wechat $wechat)
    {
        try {
            $res = $wechat->verify();
            if ($res['return_code'] === 'SUCCESS' && $res['result_code'] === 'SUCCESS') {
                Db::startTrans();
                $order = Orders::where('order_no', $res['out_trade_no'])->find();
                if ($order && $order->status == 0) {
                    $order->status = 1;
                    $order->type = 'wechat';
                    $order->save();
                    if ($order->user_coupon_id) {
                        UserCoupons::where('id', $order->user_coupon_id)->update(['status' => 2]);
                    }
                }
                Db::commit();
            }
        } catch (\Exception $e) {
            Db::rollback();
            Log::record($e->getMessage());
        }

        $wechat->wechatPay()->success()->send();
    }

    /**
     * 我的订单
     */
    public function index()
    {
        $page = $this->request->get('page');
        $length = $this->request->get('length');
        $type = $this->request->get('type');

        $orders = Orders::getUserOrders($this->auth->getUserId(), $type, $length);
        $orders->items() ? $this->success('请求成功', ['orders' => $orders->items()]) : $this->error('没有数据', [], 2);
    }

    /**
     * 订单详情
     */
    public function read($order_id)
    {
        $order = Orders::with(['design', 'refund'])->find($order_id);
        if (!$order) {
            $this->error('没有数据', [], 2);
        }
        //二维码
        $order['qrcode'] = Qrcode::createQrcode($order->id);
        //合计
        $order['amounts'] = $order['total_amount'] + $order['discount_amount'] + $order['vip_amount'];
        $this->success('请求成功', ['order' => $order]);
    }

    /**
     * 取消订单
     */
    public function cancel($order_id)
    {
        $reson = $this->request->post('reason');
        if (empty($reson)) {
            $this->error('取消原因不能为空');
        }
        $order = Orders::find($order_id);
        if (!$order) {
            $this->error('订单不存在');
        }
        if ($order->status != '1') {
            $this->error('预约已取消，无需再次申请');
        }
        Db::startTrans();
        try {
            //取消订单申请
            $refund = Refunds::create([
                'order_id' => $order_id,
                'reason' => $reson
            ]);
            //更新状态为取消中
            $order->status = 4;
            $order->save();

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
        }
        isset($e) ? $this->error($e->getMessage()) : $this->success('请求成功');
    }

    /**
     * 取消申请
     */
    public function repeal($order_id)
    {
        $order = Orders::find($order_id);
        if (!$order) {
            $this->error('订单不存在');
        }
        if ($order->status != '4') {
            $this->error('预约不在取消中状态');
        }
        $refund = Refunds::getRefundByOrderId($order_id);
        if (!$refund) {
            $this->error('没有可取消的申请');
        }
        Db::startTrans();
        try {
            //取消申请
            $refund->status = 2;
            $refund->save();
            //更新状态为待消费
            $order->status = 1;
            $order->save();

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
        }
        isset($e) ? $this->error('取消申请失败，请联系管理员') : $this->success('请求成功');
    }

    /**
     * 确认完成
     */
    public function finish($order_id)
    {
        $order = Orders::find($order_id);
        if (!$order) {
            $this->error('订单不存在');
        }
        if ($order->status != '2') {
            $this->error('已完成预约服务');
        }
        $order->status = 3;
        $result = $order->save();
        $result ? $this->success('请求成功') : $this->error('请求失败，请联系管理员');
    }

    /**
     * 确认到店服务
     */
    public function inService($order_id)
    {
        $order = Orders::find($order_id);
        if (!$order) {
            $this->error('订单不存在');
        }
        if ($order->status != '1') {
            $this->error('预约已消费');
        }
        $order->status = 2;
        $result = $order->save();
        $result ? $this->success('请求成功') : $this->error('请求失败，请联系管理员');
    }

    /**
     * 服务评价
     */
    public function comment($order_id)
    {
        $star = $this->request->post('star');
        $content = $this->request->post('content');
        if (empty($star) || empty($content)) {
            $this->error('评分和内容都不能为空');
        }
        $order = Orders::find($order_id);
        if (!$order) {
            $this->error('订单不存在');
        }
        if ($order->status != 3) {
            $this->error('订单还未完成，不能进行服务评价');
        }
        if ($order->is_comment) {
            $this->error('服务已评价，无需再次操作');
        }
        Db::startTrans();
        try {
            //评价
            OrderComment::create([
                'user_id' => $this->auth->getUserId(),
                'order_id' => $order_id,
                'star' => $star,
                'content' => $content
            ]);
            //更新订单为已评价
            $order->is_comment = 1;
            $order->comment_time = time();
            $order->save();
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
        }
        isset($e) ? $this->error('评价失败，请联系管理员') : $this->success('评价成功');
    }

    /**
     * 发送订阅消息
     */
    public function send(Wechat $wechat)
    {

        $page = $this->request->post('page');
        $order_id = $this->request->post('order_id');
        $order = Orders::with(['user', 'design', 'designService.service'])->find($order_id);
        $res = $wechat->sendSubscribeMessage($order, $page);
        if (isset($res['errcode']) && $res['errcode'] !== 0) {
            $this->error($res['errmsg'], [], $res['errcode']);
        } else {
            $this->success('请求成功');
        }
    }

    /**
     * 修改预约时间
     */
    public function time($order_id)
    {
        $time = $this->request->post('time');
        if (empty($time)) {
            $this->error('修改时间不能为空');
        }
        if (strtotime($time) < time() + 43200) {
            $this->error('抱歉，请预约12小时后的时间');
        }
        $order = Orders::find($order_id);
        if ($order->is_time) {
            $this->error('预约时间已修改过');
        }
        $order->time = $time;
        $order->is_time = 1;
        $res = $order->save();
        $res ? $this->success('请求成功') : $this->error('预约失败，请联系管理员');
    }

}
